package com.nf.mvc.mapping;

import com.nf.mvc.HandlerMapping;
import com.nf.mvc.MvcContext;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class RequestMappingHandlerMapping implements HandlerMapping {

    private Map<String, Method> handlers = new HashMap<>();

    public RequestMappingHandlerMapping() {
        resolveHandlers();
    }

    private void resolveHandlers() {

        Set<Class<?>> classes = MvcContext.getMvcContext().getScannedClasses();
        for (Class<?> aClass : classes) {
            String urlInClass = getUrl(aClass);

            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(RequestMapping.class)) {
                    //遍历类的每一个方法，方法上有注解时就认为这是一个请求处理者（Handler)
                    String urlInMethod = getUrl(method);

                    String url = urlInClass + urlInMethod;
                    addHandler(url, method);
                }
            }
        }
    }

    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String url = request.getRequestURI();
        return handlers.get(url);
    }

    private void addHandler(String url, Method method) {
        Method handler = handlers.get(url);
        if (handler != null) {
            throw new IllegalStateException("url已经有一个handler，同一个url不能有多个handler");
        }
        handlers.put(url, method);
    }

    private String getUrl(AnnotatedElement element) {
        return element.isAnnotationPresent(RequestMapping.class) ?
                element.getDeclaredAnnotation(RequestMapping.class).value()
                : "";
    }
}
